﻿namespace Jiubang.Communication.Server {
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Net.Sockets;
    using System.Threading;

    internal sealed class SocketRegister : IEnumerable<Socket> {
        private readonly Socket[] items;
        private readonly int itemLength;
        private int cursor;
        private int count;

        public SocketRegister(int capacity) {
            items = new Socket[capacity];
            itemLength = items.Length;
        }

        public Socket this[int index] { get { return items[index]; }  }

        public int Count { get { return count; } }

        public void CheckOut(ushort token) {
            items[token] = null;
            Interlocked.Decrement(ref count);
        }

        public int CheckIn(Socket socket) {
            if (Interlocked.Increment(ref count) == itemLength) {
                Interlocked.Decrement(ref count);
                throw new Exception("Socket池已满");
            }

            int original = Interlocked.Increment(ref cursor) % itemLength;
            int emptyItemIndex = original;
            while (items[emptyItemIndex] != null) {
                emptyItemIndex = Interlocked.Increment(ref cursor) % itemLength;
                if (emptyItemIndex == original) {
                    Interlocked.Decrement(ref count);
                    throw new Exception("完成一次遍历后仍然未能找到空余位置");
                }
            }
            return emptyItemIndex;
        }

        IEnumerator<Socket> IEnumerable<Socket>.GetEnumerator() {
            return ((IEnumerable<Socket>)items).GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return items.GetEnumerator();
        }
    }
}